/**
 * 
 */
package lastfmbaseball.core;

import java.util.*;

/**
 * @author DanBress
 * 
 */
public class Game
{
	private List<Inning> innings = new ArrayList<Inning>();
	private Map<HomeOrVisitor, TeamInGame> teams = new Hashtable<HomeOrVisitor, TeamInGame>();
	private final int NUMBER_OF_INNINGS = 2;

	public Game(TeamInGame homeTeam, TeamInGame visitingteam)
	{
		teams.put(HomeOrVisitor.Home, homeTeam);
		teams.put(HomeOrVisitor.Visitor, visitingteam);
	}

	public List<BaseRunner> getBaseRunners(HalfInning halfInning)
	{
		List<BaseRunner> baseRunners = halfInning.getBaseRunners();

		return baseRunners;
	}

	public PlayerInGame getBatter(HalfInning halfInning)
	{
		PlayerInGame batter = halfInning.getLastBatter();

		if (batter == null)
		{
			int inningNumber = halfInning.getInning().getInningNumber();
			if (inningNumber == 1)
			{
				HomeOrVisitor whichSideIsBatting = (halfInning.getType() == InningType.Top ? HomeOrVisitor.Visitor
						: HomeOrVisitor.Home);
				TeamInGame battingTeam = teams.get(whichSideIsBatting);
				batter = battingTeam.getBattingLineup().get(0);

			}
			else
			{
				HalfInning lastHalfInning = innings.get(inningNumber - 2)
						.getHalf(halfInning.getType());
				batter = getBatter(lastHalfInning);
			}
		}
		else
		{
			HomeOrVisitor whichSideIsBatting = (halfInning.getType() == InningType.Top ? HomeOrVisitor.Visitor
					: HomeOrVisitor.Home);
			TeamInGame battingTeam = teams.get(whichSideIsBatting);

			int currentBatterPosition = battingTeam.getBattingLineup().indexOf(
					batter);
			batter = battingTeam.getBattingLineup().get(
					(currentBatterPosition + 1)
							% battingTeam.getBattingLineup().size());
		}

		return batter;
	}

	public HalfInning getCurrentHalfInning(Inning inning)
	{
		HalfInning currentHalfInning = null;

		HalfInning top = inning.getHalf(InningType.Top);

		if (top == null)
		{
			currentHalfInning = new HalfInning(inning, InningType.Top);
			inning.addHalf(InningType.Top, currentHalfInning);
		}
		else
		{
			if (top.getNumberOfOuts() < 3)
			{
				currentHalfInning = top;
			}
			else
			{
				boolean bottomBatNeeded = inning.getInningNumber() < NUMBER_OF_INNINGS
						|| getScore(HomeOrVisitor.Home) <= getScore(HomeOrVisitor.Visitor);

				if (bottomBatNeeded)
				{
					HalfInning bottom = inning.getHalf(InningType.Bottom);
					if (bottom != null)
					{
						currentHalfInning = bottom;
					}
					else
					{
						currentHalfInning = new HalfInning(inning,
								InningType.Bottom);
						inning.addHalf(InningType.Bottom, currentHalfInning);
					}
				}
			}

		}

		return currentHalfInning;
	}

	public Inning getCurrentInning()
	{
		Inning currentInning = null;

		for (int i = 0; i < innings.size() && currentInning == null; i++)
		{
			Inning inning = innings.get(i);
			HalfInning bottom = inning.getHalf(InningType.Bottom);

			if (bottom == null || bottom.getNumberOfOuts() < 3)
			{
				currentInning = inning;
			}
		}

		if (currentInning == null)
		{
			int inningNumber = innings.size() + 1;
			if (innings.size() < NUMBER_OF_INNINGS)
			{
				currentInning = new Inning(inningNumber);

				innings.add(currentInning);
			}
			else if (getScore(HomeOrVisitor.Home) == getScore(HomeOrVisitor.Visitor))
			{
				currentInning = new Inning(inningNumber);
				innings.add(currentInning);
			}
		}

		return currentInning;
	}

	public List<Inning> getInnings()
	{
		return innings;
	}

	public PlayerInGame getPitcher(HalfInning halfInning)
	{
		HomeOrVisitor whichSideIsPitching = (halfInning.getType() == InningType.Top ? HomeOrVisitor.Home
				: HomeOrVisitor.Visitor);

		TeamInGame pitchingTeam = teams.get(whichSideIsPitching);

		return pitchingTeam.getPitcher();
	}

	public int getScore(HomeOrVisitor homeOrVisitor)
	{
		int score = 0;

		InningType inningType = (homeOrVisitor == HomeOrVisitor.Home ? InningType.Bottom
				: InningType.Top);

		for (int i = 0; i < innings.size(); i++)
		{
			HalfInning halfInning = innings.get(i).getHalf(inningType);
			if (halfInning != null)
			{
				score += halfInning.getRunsScored();
			}
		}

		return score;
	}

	public TeamInGame getTeam(HomeOrVisitor homeOrVisitor)
	{
		return teams.get(homeOrVisitor);
	}
}
